<!--
 * Copyright ©
 * #  
 * @author: zw
 * @date: 2022-01-11 
 -->


<template>
  <div class='detail'>
    <div class="w1200">
      <div class="detail-container">
        <div class="detail-main">
          <div class="cover">
            <div class="cover-img">
              <el-image :src="details.coverImgUrl">
                <div slot：placeholder class="image-slot">
                  <i class="iconfont icon-placeholder"></i>
                </div>
              </el-image>
            </div>
            <div class="cover-info">
              <div class="cover-title">
                {{details.name}}
              </div>
              <div class="cover-author" v-if="details.creator">
                <el-image :src="details.creator.avatarUrl" class="cover-avatar">
                  <div slot：placeholder class="image-slot">
                    <i class="iconfont icon-placeholder"></i>
                  </div>
                </el-image>
                <div class="cover-name">{{details.creator.nickname}}</div>
                <div class="cover-date">{{formartDate(details.createTime, 'yyyy-MM-dd')}}</div>
              </div>
              <div class="cover-tags" v-if="details.tags">
                <router-link :to="{ path: '/playlist', query: { cat: tag }}" class="tag" v-for="(tag, index) in details.tags" :key="index">#{{tag}}</router-link>
              </div>
              <div class="cover-digital">
                <span class="cover-playCount"><i class="iconfont icon-playnum"></i> {{formartNum(details.playCount)}}次</span>
                <span class="cover-collect"><i class="iconfont icon-collect"></i> {{formartNum(details.subscribedCount)}}</span>
                <span class="cover-comment"><i class="iconfont icon-comment"></i> {{formartNum(details.commentCount)}}</span>
              </div>
              <div class="cover-desc">
                <h5>歌单简介<em class="desc-close" v-if="isShowDesc" @click="isShowDesc = false"><i class="iconfont icon-closed"></i></em></h5>
                <p v-html="details.description" @click="showAllDesc"></p>
                <pre class="cover-desc-all" v-if="isShowDesc">{{details.description}}</pre>
              </div>
            </div>
          </div>
          <div class="song-main">
            <div class="song-header">
              <h4>歌曲列表 <em>{{total + '首歌'}}</em></h4>
              <span class="play-all" @click="playAllSongs"><i class="iconfont icon-audio-play"></i> 播放全部</span>
              <span :class="['collect', details.subscribed ? 'active' : '']" @click="subPlayList(details)"><i :class="['iconfont', 'icon-collect' + (details.subscribed ? '-active' : '')]"></i> {{ details.subscribed ? '已收藏' : '收藏'}}</span>
            </div>
            <template v-if="isLoading">
              <Loading />
            </template>
            <template v-else>
              <song-list :songList="songList" :stripe="true"></song-list>
              <div class="showAllSongsTips" v-if="!isLogin">
                <span @click="loginDialog">登录后查看全部歌曲</span>
              </div>
            </template>
          </div>
        </div>
        <div class="detail-aside">
          <div class="playlist-collect">
            <h3 class="aside-title">喜欢这个歌单的人</h3>
            <div class="aside-main collect-main">
              <router-link class="collect-author" :to="{ path: '/singer', query: { id: item.userId }}" v-for="item in collects" :key="item.userId">
                <el-image :src="item.avatarUrl">
                  <div slot：placeholder class="image-slot">
                    <i class="iconfont icon-placeholder"></i>
                  </div>
                </el-image>
              </router-link>
            </div>
          </div>
          <div class="playlist-recom">
            <h3 class="aside-title">相关歌单推荐</h3>
            <div class="aside-main recom-main">
              <router-link class="recom-item" :to="{ path: '/playlist/detail', query: { id: item.id }}" v-for="item in playlists" :key="item.id">
                <el-image :src="item.coverImgUrl">
                  <div slot：placeholder class="image-slot">
                    <i class="iconfont icon-placeholder"></i>
                  </div>
                </el-image>
                <div class="recom-info">
                  <div class="recom-name">{{item.name}}</div>
                  <div class="recom-author">
                    By. <router-link :to="{ path: '/user', query: { id: item.creator.userId }}">{{ item.creator.nickname }}</router-link>
                  </div>
                </div>
              </router-link>
            </div>
          </div>
          <div class="playlist-comment">
            <h3 class="aside-title">歌单评论</h3>
            <div class="aside-main comment-main">
              <div class="comment-item" v-for="item in comments" :key="item.commentId">
                <router-link :to="{ path: '/user', query: { id: item.commentId }}">
                  <el-image :src="item.user.avatarUrl">
                    <div slot：placeholder class="image-slot">
                      <i class="iconfont icon-placeholder"></i>
                    </div>
                  </el-image>
                </router-link>
                <div class="comment-info">
                  <div class="comment-userInfo">
                    <router-link :to="{ path: '/user', query: { id: item.commentId }}" class="comment-name">{{item.user.nickname}}</router-link><span class="comment-date">{{formatMsgTime(item.time)}}</span>
                  </div>
                  <div class="comment-desc">{{item.content}}</div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { computed, defineComponent, onMounted, reactive, toRefs, watch } from 'vue';
import { onBeforeRouteUpdate } from 'vue-router';
import { PLAYLISTDETAIL, SONGDETAIL, PLAYLISTSCOLLECT, PLAYLISTRELATED, PLAYLISTCOMMENT, SUBPLAYLIST } from "@/api";
import { useInstance } from "@/hooks";
import { formatSongs, formartNum, formartDate, formatMsgTime } from "@/utils";
export default defineComponent({
  name: 'Detail',
  setup(props, { emit, slots }) {
    const { $router: router, $Message: $message, $store: store } = useInstance();
    const isLogin = computed(() => store.getters.isLogin);
    const { info, _initialize, getAllSongs } = initializeRequest($message, isLogin);
    // 播放列表为当前歌单的全部歌曲
    const playAllSongs = () => {
      store.dispatch('playAll', { list: info.songList });
      store.commit('SET_PLAYLISTTIPS', true);
    };
    // 收藏、取消歌单
    const subPlayList = async ({ id, subscribed }) => {
      //  1：收藏 2取消
      const { code } = await SUBPLAYLIST({ id: id, t: !subscribed ? 1 : 2 });
      if (code !== 200) return $message.error('数据请求失败');
      info.details.subscribed = !info.details.subscribed;
    };
    watch(() => isLogin.value, (newVal, oldVal) => {
      if (newVal) {
        const ids = info.details.trackIds;
        getAllSongs(ids);
      } else {
        info.songList = formatSongs(info.details.tracks);
        info.total = info.details.tracks.length;
      }
    });
    onMounted(_initialize.bind(null, router.currentRoute.value.query.id));
    onBeforeRouteUpdate((to) => {
      info.songList = [];
      info.total = 0;
      info.id = to.query.id;
      _initialize(info.id);
    });
    return {
      ...toRefs(info),
      isLogin,
      formartNum,
      formartDate,
      formatMsgTime,
      playAllSongs,
      subPlayList
    }
  }
});
function initializeRequest($message, isLogin) {
  const info = reactive({
    id: '',
    details: {},
    songList: [],
    collects: [],
    playlists: [],
    comments: [],
    total: 0,
    isLoading: true,
    isShowDesc: false
  });
  const _initialize = (id) => {
    getDetail({ id: id, s: 8 });// 歌单详情
    getCollect({ id: id, limit: 18 });// 歌单收藏者
    getRecom({ id: id });// 相关歌单推荐
    getComment({ id: id, limit: 9 });// 歌单评论
  };
  // 登录及未登录下获取歌单中歌曲的列表
  const getDetail = async (params) => {
    info['isLoading'] = true;
    const defaults = { id: '', s: 8 };
    const { code, playlist } = await PLAYLISTDETAIL({ ...defaults, ...params });

    if (code !== 200) return $message.error('数据请求失败');
    info['details'] = playlist;
    if (isLogin.value) {
      const ids = playlist.trackIds;
      getAllSongs(ids);
    } else {
      info['songList'] = formatSongs(playlist.tracks)
      info['total'] = info['songList'].length
      info['isLoading'] = false
    }
  }
  // 订阅该歌单的用户列表
  const getCollect = async (params) => {
    const defaults = { id: '', limit: 20, offset: 0 };
    const { code, subscribers } = await PLAYLISTSCOLLECT({ ...defaults, ...params });
    if (code !== 200) {
      return proxy.$msg.error('数据请求失败')
    }
    info.collects = subscribers
  };
  // 相关歌单推荐
  const getRecom = async (params = { id: "" }) => {
    const { code, playlists } = await PLAYLISTRELATED(params);
    if (code !== 200) return $message.error('数据请求失败');
    info.playlists = playlists;
  };
  // 歌单精彩评论
  const getComment = async (params) => {
    const defaults = { id: '', limit: 20, offset: 0, before: 0 };
    const { code, comments } = await PLAYLISTCOMMENT({ ...defaults, ...params });
    if (code !== 200) return $message.error('数据请求失败');
    info.comments = comments;
  };
  // 登录后根据ids获取所有歌曲列表
  const getAllSongs = async (ids) => {
    const sliceArr = []
    const num = 500
    let idsArr = []
    const defaults = { ids: '', timestamp: 0 };
    // 数组过长 每500份一组
    for (let index = 0; index < ids.length; index += num) {
      sliceArr.push(ids.slice(index, index + num));
    }

    for (let i = 0; i < sliceArr.length; i++) {
      const arrs = sliceArr[i].map(d => d.id);
      info['isLoading'] = true;
      const params = { ids: arrs.join(','), timestamp: new Date().valueOf() + i }
      const { songs, privileges } = await SONGDETAIL({ ...defaults, ...params });
      idsArr = idsArr.concat(formatSongs(songs, privileges))
    }

    info['songList'] = idsArr;
    info['total'] = idsArr.length;
    info['isLoading'] = false;
  }
  return {
    info,
    _initialize,
    getAllSongs
  }
}
</script>

<style lang='scss' scoped>
.detail-container {
  display: flex;
  flex-direction: row;
  flex: 1;
  flex-basis: auto;
  box-sizing: border-box;
  padding: 40px 0 0 0;
}
.detail-main {
  flex: 1;
  padding-bottom: 100px;
  overflow: hidden;
}
.detail-aside {
  width: 300px;
  padding-left: 20px;

  .aside-title {
    position: relative;
    font-size: 16px;
    line-height: 24px;

    &::before {
      content: "";
      display: inline-block;
      width: 4px;
      height: 18px;
      margin: 3px 5px 0 0;
      border-radius: 2px;
      background: $color-theme;
      vertical-align: top;
    }
  }
}
.cover {
  display: flex;
}
.cover-img {
  position: relative;
  width: 280px;
  height: 280px;

  &::after {
    position: absolute;
    top: 0;
    left: 0;
    z-index: -1;
    width: 100%;
    height: 100%;
    content: "";
    transform: scale(0.95) translateX(5%);
    background: #f0f0f0;
  }
}
.cover-info {
  flex: 1;
  padding-left: 40px;

  .cover-title {
    font-size: 24px;
    font-weight: bold;
  }
}
.cover-author {
  padding: 15px 0 10px;

  .cover-avatar {
    display: inline-block;
    width: 32px;
    height: 32px;
    border-radius: 100%;
    vertical-align: top;
  }

  .cover-name,
  .cover-date {
    display: inline-block;
    padding: 0 10px;
    line-height: 32px;
  }

  .cover-date {
    color: #999;
  }
}
.cover-tags {
  padding-bottom: 5px;
  line-height: 16px;

  .tag {
    display: inline-block;
    margin-right: 5px;
    font-size: 12px;
    color: $color-theme;
  }
}
.cover-playCount,
.cover-collect,
.cover-comment {
  display: inline-block;
  padding: 0 20px 5px 0;
  line-height: 16px;
  font-size: 14px;
  color: #999;

  i {
    vertical-align: top;
  }
}
.cover-desc {
  position: relative;

  h5 {
    padding: 30px 0 5px;
    line-height: 20px;
    font-size: 14px;
    color: #333;
  }

  .desc-close {
    position: absolute;
    top: 30px;
    right: 0;
    cursor: pointer;
  }

  p {
    line-height: 22px;
    font-size: 14px;
    color: #999;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    word-break: break-all;
    cursor: pointer;
  }

  .cover-desc-all {
    position: absolute;
    top: 70px;
    left: 10px;
    z-index: 1;
    width: calc(100% - 20px);
    padding: 10px;
    margin: -10px;
    max-height: 250px;
    line-height: 22px;
    font-size: 14px;
    white-space: pre-line;
    font-family: inherit;
    color: #999;
    background: #fff;
    overflow-y: scroll;
    box-shadow: 0 2px 10px 0 rgba(52, 52, 52, 0.1);
  }
}

.song-header {
  display: flex;
  padding: 30px 0 10px;

  h4 {
    flex: 1;
    font-size: 20px;
    line-height: 40px;

    em {
      display: inline-block;
      padding-left: 10px;
      font-size: 12px;
      line-height: 14px;
      font-style: normal;
      font-weight: normal;
      color: #666;
      vertical-align: baseline;
    }
  }

  span {
    display: flex;
    line-height: 16px;
    align-items: center;
    justify-content: center;
    border-radius: 50px;
    padding: 7px 20px;
    cursor: pointer;
    margin: 5px 0 5px 15px;
    transition: all 0.4s;
    background: #f0f0f0;
    color: #333;

    i {
      margin-right: 3px;
    }
  }

  .play-all {
    color: #fff;
    background: $color-theme;

    i {
      color: #fff;
    }
  }

  .collect.active,
  .collect.active i {
    color: $color-theme;
  }
}

.showAllSongsTips {
  text-align: center;
  padding: 40px 0;

  span {
    display: inline-block;
    display: flex;
    line-height: 16px;
    align-items: center;
    justify-content: center;
    border-radius: 50px;
    padding: 7px 20px;
    color: #fff;
    background: $color-theme;
    cursor: pointer;
  }
}

.aside-main {
  font-size: 0;
  padding-bottom: 30px;

  .collect-author {
    display: inline-block;
    width: 40px;
    height: 40px;
    margin: 10px 5px;
    border-radius: 100%;
    overflow: hidden;
  }
}

.collect-main {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  margin: 0 -10px;
}
.recom-main {
  .el-image {
    width: 60px;
    height: 60px;
    border-radius: 4px;
    overflow: hidden;
  }

  .recom-item {
    display: flex;
    padding: 10px 0;
  }

  .recom-info {
    flex: 1;
    padding-left: 10px;
  }

  .recom-name {
    width: 100%;
    height: 20px;
    line-height: 20px;
    font-size: 14px;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    word-break: break-all;
    cursor: pointer;
  }

  .recom-author {
    height: 20px;
    line-height: 20px;
    margin-top: 20px;
    font-size: 12px;
    color: #999;

    a {
      color: #666;
    }
  }
}

.comment-main {
  font-size: 0;

  .el-image {
    width: 40px;
    height: 40px;
    border-radius: 100%;
    overflow: hidden;
  }

  .comment-item {
    display: flex;
    padding: 10px 0;
  }

  .comment-info {
    flex: 1;
    padding-left: 10px;
  }

  .comment-userInfo {
    width: 100%;
    font-size: 0;
  }

  .comment-name {
    font-size: 14px;
    line-height: 14px;
    font-weight: bold;
  }

  .comment-desc {
    font-size: 12px;
    color: #666;
    line-height: 1.6;
    padding: 5px 10px;
    background: #f5f5f5;
    margin: 5px 0;
    border-radius: 3px;
  }

  .comment-date {
    display: inline-block;
    padding-left: 5px;
    font-size: 12px;
    color: #666;
  }
}

.el-table /deep/thead th {
  font-weight: normal;
  background-color: #f5f7fa;
}
</style>
